import { ref } from "vue";
import { Graph, Shape } from "@antv/x6";
import { Stencil } from "@antv/x6-plugin-stencil";
import { Keyboard } from "@antv/x6-plugin-keyboard";
import { Selection } from "@antv/x6-plugin-selection";
import { Clipboard } from "@antv/x6-plugin-clipboard";
import { History } from "@antv/x6-plugin-history";
import { Snapline } from "@antv/x6-plugin-snapline";
import { Transform } from "@antv/x6-plugin-transform";
import { EDGE_TOOLS, NODE_TOOLS, list1, list2 } from "./components/index";

// 控制连接桩显示/隐藏
const showPorts = (ports: NodeListOf<SVGElement>, show: boolean) => {
  for (let i = 0, len = ports.length; i < len; i += 1) {
    ports[i].style.visibility = show ? "visible" : "hidden";
  }
};

export const AntVData = () => {
  const initGraph = (containerEl: HTMLElement, leftEl: HTMLElement) => {
    const graph = new Graph({
      container: containerEl!,
      grid: {
        // visible: true,
        size: 2,
      },
      panning: {
        enabled: true,
        modifiers: "Ctrl",
      },
      background: {
        color: "#f2f7fa",
      },
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: "ctrl",
        minScale: 0.5,
        maxScale: 3,
      },
      connecting: {
        router: "manhattan",
        anchor: "center",
        connectionPoint: "anchor",
        allowBlank: false,
        snap: {
          radius: 20,
        },
        createEdge() {
          return new Shape.Edge({
            attrs: {
              line: {
                stroke: "#A2B1C3",
                strokeWidth: 2,
                targetMarker: {
                  name: "block",
                  width: 12,
                  height: 8,
                },
              },
            },
            zIndex: 0,
          });
        },
        validateConnection({ targetMagnet }) {
          return !!targetMagnet;
        },
      },
      highlighting: {
        magnetAdsorbed: {
          name: "stroke",
          args: {
            attrs: {
              fill: "#5F95FF",
              stroke: "#5F95FF",
            },
          },
        },
      },
    });

    graph
      .use(
        new Clipboard({
          enabled: true,
        })
      )
      .use(
        new Selection({
          enabled: true,
          rubberband: true,
          showNodeSelectionBox: true,
        })
      )
      .use(
        new Keyboard({
          enabled: true,
        })
      )
      .use(
        new History({
          enabled: true,
        })
      )
      .use(
        new Snapline({
          enabled: true,
        })
      )
      .use(
        new Transform({
          resizing: true,
          rotating: true,
        })
      );

    // #region 快捷键与事件

    // 复制
    graph.bindKey(["meta+c", "ctrl+c"], () => {
      const cells = graph.getSelectedCells();
      if (cells.length) {
        graph.copy(cells);
      }
      return false;
    });

    // 粘贴
    graph.bindKey(["meta+v", "ctrl+v"], () => {
      if (!graph.isClipboardEmpty()) {
        const cells = graph.paste({ offset: 32 });
        graph.cleanSelection();
        graph.select(cells);
      }
      return false;
    });

    // 剪切
    graph.bindKey(["meta+x", "ctrl+x"], () => {
      const cells = graph.getSelectedCells();
      if (cells.length) {
        graph.cut(cells);
      }
      return false;
    });

    // 撤回
    graph.bindKey(["meta+z", "ctrl+z"], () => {
      if (graph.canUndo()) {
        graph.undo();
      }
      return false;
    });

    // 选择全部;
    graph.bindKey(["meta+a", "ctrl+a"], () => {
      const nodes = graph.getNodes();
      if (nodes) {
        graph.select(nodes);
      }
    });

    // 删除
    graph.bindKey("backspace", () => {
      const cells = graph.getSelectedCells();
      if (cells.length) {
        graph.removeCells(cells);
      }
    });

    const handleReData = (flag: boolean) => {
      const container = containerEl;
      const ports = container.querySelectorAll(
        ".x6-port-body"
      ) as NodeListOf<SVGElement>;
      console.log("node:mouseenter", "ports === ", ports);
      showPorts(ports, flag);
    };

    graph.on("node:mouseenter", ({ node }) => {
      // node.addTools(NODE_TOOLS);
      handleReData(true);
    });

    graph.on("node:mouseleave", ({ cell }) => {
      // cell.removeTools();
      handleReData(false);
    });

    graph.on("node:click", ({ cell }) => {
      // cell.removeTools();
      handleReData(false);
    });

    graph.on("edge:mouseenter", ({ e, edge, view }) => {
      edge.addTools(EDGE_TOOLS);
    });

    graph.on("edge:mouseleave", ({ cell }) => {
      cell.removeTools();
    });

    const stencil = new Stencil({
      title: "流程图",
      target: graph,
      stencilGraphWidth: 200,
      stencilGraphHeight: 0,
      collapsable: true,
      groups: [
        {
          title: "基础流程图",
          name: "group1",
        },
        {
          title: "系统设计图",
          name: "group2",
          // graphHeight: 250,
          layoutOptions: {
            // rowHeight: 70,
          },
        },
      ],
      layoutOptions: {
        columns: 2,
        columnWidth: 100,
        // rowHeight: 55,
      },
    });

    leftEl!.appendChild(stencil.container);

    const ports = {
      groups: {
        top: {
          position: "top",
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: "#5F95FF",
              strokeWidth: 1,
              fill: "#fff",
              style: {
                visibility: "hidden",
              },
            },
          },
        },
        right: {
          position: "right",
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: "#5F95FF",
              strokeWidth: 1,
              fill: "#fff",
              style: {
                visibility: "hidden",
              },
            },
          },
        },
        bottom: {
          position: "bottom",
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: "#5F95FF",
              strokeWidth: 1,
              fill: "#fff",
              style: {
                visibility: "hidden",
              },
            },
          },
        },
        left: {
          position: "left",
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: "#5F95FF",
              strokeWidth: 1,
              fill: "#fff",
              style: {
                visibility: "hidden",
              },
            },
          },
        },
      },
      items: [
        {
          group: "top",
        },
        {
          group: "right",
        },
        {
          group: "bottom",
        },
        {
          group: "left",
        },
      ],
    };

    Graph.registerNode(
      "custom-rect",
      {
        inherit: "rect",
        width: 66,
        height: 36,
        attrs: {
          body: {
            strokeWidth: 1,
            stroke: "#5F95FF",
            fill: "#EFF4FF",
          },
          text: {
            fontSize: 12,
            fill: "#262626",
          },
        },
        ports: { ...ports },
      },
      true
    );

    Graph.registerNode(
      "custom-polygon",
      {
        inherit: "polygon",
        width: 66,
        height: 36,
        attrs: {
          body: {
            strokeWidth: 1,
            stroke: "#5F95FF",
            fill: "#EFF4FF",
          },
          text: {
            fontSize: 12,
            fill: "#262626",
          },
        },
        ports: {
          ...ports,
          items: [
            {
              group: "top",
            },
            {
              group: "bottom",
            },
          ],
        },
      },
      true
    );

    Graph.registerNode(
      "custom-circle",
      {
        inherit: "circle",
        width: 45,
        height: 45,
        attrs: {
          body: {
            strokeWidth: 1,
            stroke: "#5F95FF",
            fill: "#EFF4FF",
          },
          text: {
            fontSize: 12,
            fill: "#262626",
          },
        },
        ports: { ...ports },
      },
      true
    );

    Graph.registerNode(
      "custom-image",
      {
        inherit: "rect",
        width: 52,
        height: 52,
        markup: [
          {
            tagName: "rect",
            selector: "body",
          },
          {
            tagName: "image",
          },
          {
            tagName: "text",
            selector: "label",
          },
        ],
        attrs: {
          body: {
            stroke: "#5F95FF",
            fill: "#5F95FF",
          },
          image: {
            width: 26,
            height: 26,
            refX: 13,
            refY: 16,
          },
          label: {
            refX: 3,
            refY: 2,
            textAnchor: "left",
            textVerticalAnchor: "top",
            fontSize: 12,
            fill: "#fff",
          },
        },
        ports: { ...ports },
      },
      true
    );

    const handleStencilData = () => {
      return list1.map((item) => {
        return graph.createNode(item);
      });
    };
    const imageNodes = list2.map((item) =>
      graph.createNode({
        shape: "custom-image",
        label: item.label,
        attrs: {
          image: {
            "xlink:href": item.image,
          },
        },
      })
    );
    stencil.load(imageNodes, "group2");
    stencil.load(handleStencilData(), "group1");
  };

  return {
    initGraph,
  };
};
